package com.blog.cmrpersonalblog.controller;

import com.blog.cmrpersonalblog.annotation.RateLimit;
import com.blog.cmrpersonalblog.common.Result;
import com.blog.cmrpersonalblog.dto.auth.request.*;
import com.blog.cmrpersonalblog.dto.auth.response.EmailVerificationResponse;
import com.blog.cmrpersonalblog.dto.auth.response.LoginResponse;
import com.blog.cmrpersonalblog.enums.LimitType;
import com.blog.cmrpersonalblog.service.AuthService;
import com.blog.cmrpersonalblog.service.EmailVerificationService;
import com.blog.cmrpersonalblog.service.PasswordResetService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 用户端认证控制器
 * 提供用户端的登录和注册功能
 */
@Slf4j
@RestController
@RequestMapping("/user/auth")
@CrossOrigin(origins = "*", maxAge = 3600)
public class UserAuthController {

    @Resource
    private AuthService authService;

    @Resource
    private EmailVerificationService emailVerificationService;

    @Resource
    private PasswordResetService passwordResetService;

    /**
     * 用户登录
     */
    @PostMapping("/login")
    @RateLimit(count = 5, time = 60, limitType = LimitType.IP, message = "登录过于频繁，请稍后再试")
    public Result<LoginResponse> login(@RequestBody @Validated LoginRequest loginRequest) {
        log.info("用户端登录请求: userName={}", loginRequest.getUserName());
        try {
            LoginResponse response = authService.login(loginRequest);
            log.info("用户端登录成功: userId={}, userName={}", response.getUserId(), response.getUserName());
            return Result.success("登录成功", response);
        } catch (Exception e) {
            log.error("用户端登录失败: userName={}, error={}", loginRequest.getUserName(), e.getMessage());
            return Result.error(e.getMessage());
        }
    }

    /**
     * 用户注册
     */
    @PostMapping("/register")
    @RateLimit(count = 3, time = 3600, limitType = LimitType.IP, message = "注册过于频繁，请1小时后再试")
    public Result<LoginResponse> register(@RequestBody @Validated RegisterRequest registerRequest) {
        log.info("用户注册请求: userName={}, email={}", registerRequest.getUserName(), registerRequest.getEmail());
        try {
            LoginResponse response = authService.register(registerRequest);
            log.info("用户注册成功: userId={}, userName={}", response.getUserId(), response.getUserName());
            return Result.success("注册成功", response);
        } catch (Exception e) {
            log.error("用户注册失败: userName={}, error={}", registerRequest.getUserName(), e.getMessage());
            return Result.error(e.getMessage());
        }
    }

    /**
     * 用户注销
     */
    @PostMapping("/logout")
    public Result<Void> logout() {
        try {
            boolean success = authService.logout();
            if (success) {
                log.info("用户端注销成功");
                return Result.success("注销成功");
            } else {
                return Result.error("注销失败");
            }
        } catch (Exception e) {
            log.error("用户端注销失败: error={}", e.getMessage());
            return Result.error("注销失败：" + e.getMessage());
        }
    }

    /**
     * 获取当前用户信息
     */
    @GetMapping("/userinfo")
    public Result<LoginResponse> getUserInfo() {
        try {
            LoginResponse response = authService.getCurrentUser();
            return Result.success("获取用户信息成功", response);
        } catch (Exception e) {
            log.error("获取用户信息失败: error={}", e.getMessage());
            return Result.unauthorized(e.getMessage());
        }
    }

    /**
     * 刷新token
     */
    @PostMapping("/refresh")
    public Result<LoginResponse> refreshToken() {
        try {
            LoginResponse response = authService.refreshToken();
            return Result.success("刷新成功", response);
        } catch (Exception e) {
            log.error("刷新token失败: error={}", e.getMessage());
            return Result.unauthorized(e.getMessage());
        }
    }

    /**
     * 发送邮箱验证码
     */
    @PostMapping("/send-verification-code")
    @RateLimit(count = 1, time = 60, limitType = LimitType.IP, message = "发送验证码过于频繁，请1分钟后再试")
    public Result<EmailVerificationResponse> sendVerificationCode(@RequestBody @Validated SendVerificationCodeRequest request) {
        String clientIp = getClientIp();
        String userAgent = getRequest().getHeader("User-Agent");

        log.info("发送验证码请求: email={}, type={}", request.getEmail(), request.getVerificationType());
        try {
            EmailVerificationResponse response = emailVerificationService.sendVerificationCode(request, clientIp, userAgent);
            if (response.getSuccess()) {
                log.info("验证码发送成功: email={}, type={}", request.getEmail(), request.getVerificationType());
                return Result.success(response.getMessage(), response);
            } else {
                log.warn("验证码发送失败: email={}, type={}, message={}",
                        request.getEmail(), request.getVerificationType(), response.getMessage());
                return Result.error(response.getMessage());
            }
        } catch (Exception e) {
            log.error("发送验证码异常: email={}, type={}, error={}",
                     request.getEmail(), request.getVerificationType(), e.getMessage());
            return Result.error("发送失败，请稍后重试");
        }
    }

    /**
     * 验证邮箱验证码
     */
    @PostMapping("/verify-email-code")
    public Result<Void> verifyEmailCode(@RequestBody @Validated VerifyEmailCodeRequest request) {
        log.info("验证邮箱验证码请求: email={}, type={}", request.getEmail(), request.getVerificationType());
        try {
            boolean isValid = emailVerificationService.verifyCode(request);
            if (isValid) {
                log.info("邮箱验证码验证成功: email={}, type={}", request.getEmail(), request.getVerificationType());
                return Result.success("验证码验证成功");
            } else {
                log.warn("邮箱验证码验证失败: email={}, type={}", request.getEmail(), request.getVerificationType());
                return Result.error("验证码无效或已过期");
            }
        } catch (Exception e) {
            log.error("验证邮箱验证码异常: email={}, type={}, error={}",
                     request.getEmail(), request.getVerificationType(), e.getMessage());
            return Result.error("验证失败，请稍后重试");
        }
    }

    /**
     * 忘记密码 - 发送重置邮件
     */
    @PostMapping("/forgot-password")
    public Result<EmailVerificationResponse> forgotPassword(@RequestBody @Validated ForgotPasswordRequest request) {
        String clientIp = getClientIp();
        String userAgent = getRequest().getHeader("User-Agent");

        log.info("忘记密码请求: email={}", request.getEmail());
        try {
            EmailVerificationResponse response = passwordResetService.sendResetPasswordEmail(request, clientIp, userAgent);
            if (response.getSuccess()) {
                log.info("密码重置邮件发送成功: email={}", request.getEmail());
                return Result.success(response.getMessage(), response);
            } else {
                log.warn("密码重置邮件发送失败: email={}, message={}", request.getEmail(), response.getMessage());
                return Result.error(response.getMessage());
            }
        } catch (Exception e) {
            log.error("忘记密码异常: email={}, error={}", request.getEmail(), e.getMessage());
            return Result.error("发送失败，请稍后重试");
        }
    }

    /**
     * 验证重置令牌
     */
    @GetMapping("/validate-reset-token")
    public Result<Void> validateResetToken(@RequestParam String resetToken) {
        log.info("验证重置令牌请求: token={}", resetToken);
        try {
            boolean isValid = passwordResetService.validateResetToken(resetToken);
            if (isValid) {
                log.info("重置令牌验证成功: token={}", resetToken);
                return Result.success("重置令牌有效");
            } else {
                log.warn("重置令牌验证失败: token={}", resetToken);
                return Result.error("重置令牌无效或已过期");
            }
        } catch (Exception e) {
            log.error("验证重置令牌异常: token={}, error={}", resetToken, e.getMessage());
            return Result.error("验证失败，请稍后重试");
        }
    }

    /**
     * 重置密码
     */
    @PostMapping("/reset-password")
    public Result<Void> resetPassword(@RequestBody @Validated ResetPasswordRequest request) {
        String clientIp = getClientIp();
        String userAgent = getRequest().getHeader("User-Agent");

        log.info("重置密码请求: token={}", request.getResetToken());
        try {
            boolean success = passwordResetService.resetPassword(request, clientIp, userAgent);
            if (success) {
                log.info("密码重置成功: token={}", request.getResetToken());
                return Result.success("密码重置成功");
            } else {
                log.warn("密码重置失败: token={}", request.getResetToken());
                return Result.error("密码重置失败，请检查重置令牌是否有效");
            }
        } catch (Exception e) {
            log.error("重置密码异常: token={}, error={}", request.getResetToken(), e.getMessage());
            return Result.error("重置失败，请稍后重试");
        }
    }

    /**
     * 获取当前请求对象
     */
    private HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes != null ? attributes.getRequest() : null;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp() {
        HttpServletRequest request = getRequest();
        if (request == null) {
            return "unknown";
        }

        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        // 如果是多级代理，取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(",")).trim();
        }

        return ip;
    }
}
